package com.boesch.electroOffice.business.birt;

import java.io.OutputStream;

import javax.servlet.http.HttpServletResponse;

import org.eclipse.birt.report.engine.api.EngineException;
import org.eclipse.birt.report.engine.api.HTMLActionHandler;
import org.eclipse.birt.report.engine.api.HTMLRenderOption;
import org.eclipse.birt.report.engine.api.HTMLServerImageHandler;
import org.eclipse.birt.report.engine.api.IReportEngine;
import org.eclipse.birt.report.engine.api.IReportRunnable;
import org.eclipse.birt.report.engine.api.IRunAndRenderTask;
import org.eclipse.birt.report.engine.api.RenderOption;

import com.boesch.electroOffice.business.common.BusinessException;
import com.boesch.electroOffice.business.common.BusinessExceptionMessages;
import com.boesch.electroOffice.model.birt.HTMLReportOptions;
import com.boesch.electroOffice.model.birt.ReportOptions;

public class ReportRenderer {
	private IReportEngine birtEngine = null;

	public enum supportedFormats {
		HTML, PDF, XLS, DOC;
	}

	public ReportRenderer(String birtHome, String resourceFolder, String odaJDBCDriverClassPath) {
		birtEngine = BirtEngine.getBirtEngine(birtHome, resourceFolder, odaJDBCDriverClassPath);
	}

	public ReportRenderer(String birtHome, String resourceFolder) {
		birtEngine = BirtEngine.getBirtEngine(birtHome, resourceFolder);
	}

	public ReportRenderer() {
		birtEngine = BirtEngine.getBirtEngine(null, null);
	}

	private void render(ReportOptions options, OutputStream outputStream, String fileName) throws BusinessException {
		IReportRunnable runnable;
		try {
			runnable = birtEngine.openReportDesign(options.getReportName());
			IRunAndRenderTask task = birtEngine.createRunAndRenderTask(runnable);
			RenderOption renderOption = getRenderOption(options);
			if (fileName != null && fileName.length() > 0) {
				renderOption.setOutputFileName(fileName);
			} else {
				renderOption.setOutputStream(outputStream);
			}
			task.setRenderOption(renderOption);
			if (options.getParameters() != null) {
				task.setParameterValues(options.getParameters());
			}
			
			if (null != options.getLocale()) {
				task.setLocale(options.getLocale());
			}
			
			task.run();
			task.close();
		} catch (EngineException e) {
			throw new BusinessException(BusinessExceptionMessages.BIRT_FAILED_TO_CREATE_REPORT.getValue(), e);
		}
	}

	public void render(ReportOptions options, OutputStream outputStream) throws BusinessException {
		checkInputs(options, true);
		setHeader(options);
		render(options, outputStream, null);
	}

	public void render(ReportOptions options, String fileName) throws BusinessException {
		checkInputs(options, false);
		if (fileName == null || fileName.length() == 0) {
			throw new BusinessException(BusinessExceptionMessages.BIRT_FILENAME_MISSING.getValue());
		}
		render(options, null, fileName);
	}

	private void checkInputs(ReportOptions options, boolean isStream) throws BusinessException {
		String format = options.getOutFormat();
		if (format == null || format.length() == 0) {
			throw new BusinessException(BusinessExceptionMessages.BIRT_UNKNONW_FORMAT.getValue());
		} else {
			boolean isSupported = false;
			for (supportedFormats supportedFormat : supportedFormats.values()) {
				if (supportedFormat.toString().equalsIgnoreCase(format)) {
					isSupported = true;
				}
			}
			if (!isSupported) {
				throw new BusinessException(BusinessExceptionMessages.BIRT_UNKNONW_FORMAT.getValue());
			}
		}
		if (options.getReportName() == null || options.getReportName().length() == 0) {
			throw new BusinessException(BusinessExceptionMessages.BIRT_REPORT_NAME_MISSING.getValue());
		}
		if (isStream) {
			if (options.getResponse() == null) {
				throw new BusinessException(BusinessExceptionMessages.BIRT_HTTP_RESPONSE_MISSING.getValue());
			}
		}
	}

	private void setHeader(ReportOptions options) {
		String outFormat = options.getOutFormat();
		if (outFormat.equalsIgnoreCase(supportedFormats.PDF.toString())) {
			setHeader(options, "application/pdf");
		} else if (outFormat.equalsIgnoreCase(supportedFormats.XLS.toString())) {
			setHeader(options, "application/vnd.ms-excel");
		} else if (outFormat.equalsIgnoreCase(supportedFormats.DOC.toString())) {
			setHeader(options, "application/msword");
		}
	}

	private void setHeader(ReportOptions options, String defaultContentType) {
		HttpServletResponse response = options.getResponse();
		response.setContentType(options.getContentType() != null ? options.getContentType() : defaultContentType);
		String contentDisposition = (options.isRenderInline() ? "inline" : "attachment");
		if (options.getFileNameHeader() != null && options.getFileNameHeader().length() > 0) {
			contentDisposition += "; filename=\"";
			contentDisposition += options.getFileNameHeader();
			contentDisposition += "\"";
		}
		response.addHeader("Content-Disposition", contentDisposition);
	}

	private RenderOption getRenderOption(ReportOptions options) {
		RenderOption renderOption = null;
		if (options.getOutFormat().equalsIgnoreCase(supportedFormats.HTML.toString())) {
			HTMLRenderOption hro = new HTMLRenderOption();
			if (options instanceof HTMLReportOptions) {
				HTMLReportOptions htmlOptions = (HTMLReportOptions) options;
				hro.setImageDirectory(htmlOptions.getServletContext().getRealPath(null) + htmlOptions.getImageURL());
				hro.setBaseImageURL(htmlOptions.getRequest().getContextPath() + htmlOptions.getImageURL());
				hro.setEmbeddable(options.isRenderInline());
			}
			hro.setActionHandler(new HTMLActionHandler());
			hro.setImageHandler(new HTMLServerImageHandler());
			renderOption = hro;
		} else {
			renderOption = new RenderOption();
		}
		renderOption.setOutputFormat(options.getOutFormat().toLowerCase());
		return renderOption;
	}
}
